﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HerGoS.Administration.Entities;
using System.Data;
using HerGoS.Interfaces;
using HerGoS.DAO;
using HerGoS.Administration.Exceptions;

namespace HerGoS.Administration.Engine
{
    public class GestorRoles
    {
        /// <summary>
        /// Permite obtener el Rol segun su identificador
        /// </summary>
        /// <param name="OID">Identificador</param>
        /// <returns>Rol</returns>
        public static Rol Obtener(int OID)
        {
            try
            {
                IRepository repo = RepositoryFactory.Create(Config.RepositoryName);
                repo.Nombre = "ROLES_SP";
                repo.AddParameter("@ACCION", "BYID");
                repo.AddParameter("@ID", OID);
                DataTable dt = repo.ExecuteDataTable();
                Rol result = dt.ToGenericList<Rol>(RolConverter).FirstOrDefault();
                return result;
            }
            catch (Exception ex)
            {
                throw new RolGetException(ex);
            }
        }

        /// <summary>
        /// Permite obtener los Roles de un usuario
        /// </summary>
        /// <param name="nick">nombre de usuario</param>
        /// <returns>Lista de roles</returns>
        public static List<Rol> ObtenerxUsuario(int idusuario)
        {            
            try
            {
                IRepository repo = RepositoryFactory.Create(Config.RepositoryName);
                repo.Nombre = "ROLES_SP";
                repo.AddParameter("@ACCION", "BYUSER");
                repo.AddParameter("@ID", null);
                repo.AddParameter("@CODIGO", null);
                repo.AddParameter("@NOMBRE", null);
                repo.AddParameter("@IDUSUARIO", idusuario);
                DataTable dt = repo.ExecuteDataTable();
                List<Rol> result = dt.ToGenericList<Rol>(RolConverter);
                return result;
            }
            catch (Exception ex)
            {
                throw new RolGetException(ex);
            }
        }


        /// <summary>
        /// Permite obtener los modulos de un Rol
        /// </summary>
        /// <param name="nick">id del rol</param>
        /// <returns>Lista de modulos</returns>
        public static List<Modulo> ObtenerModulos(int idrol)
        {
            try
            {
                IRepository repo = RepositoryFactory.Create(Config.RepositoryName);
                repo.Nombre = "ROLES_SP";
                repo.AddParameter("@ACCION", "MODULOS");
                repo.AddParameter("@ID", idrol);
                DataTable dt = repo.ExecuteDataTable();
                List<Modulo> result = dt.ToGenericList<Modulo>(GestorModulo.ModuloConverter);
                return result;
            }
            catch (Exception ex)
            {
                throw new RolGetException(ex);
            }
        }

        public static void Guardar(Rol rol)
        {
            try
            {
                IRepository repo = RepositoryFactory.CreateTransactional(Config.RepositoryName);
                repo.Nombre = "ROLES_PROC";
                repo.AddParameter("@ACCION", rol.Persistencia);
                repo.AddParameter("@ID", rol.OID);
                repo.AddParameter("@CODIGO", rol.Codigo);
                repo.AddParameter("@NOMBRE", rol.Nombre);
                repo.AddParameter("@IDUSUARIO", HGSContext.Usuario.OID);
                rol.OID = repo.ExecuteReturnValue().ToInteger();
                repo.Commit();

                GuardarModulos(rol);

                GestorBitacora.Guardar(rol);
            }
            catch (Exception ex)
            {
                throw new RolSetException(ex);
            }
        }

        private static void GuardarModulos(Rol rol)
        {
            if (rol.Persistencia != EstadoPersistencia.INSERT && rol.Persistencia != EstadoPersistencia.UPDATE)
                return;

                IRepository repo = RepositoryFactory.CreateTransactional(Config.RepositoryName);
                repo.Nombre = "ROLES_MODULOS_PROC";
                repo.AddParameter("@ACCION", "DELETEALL");
                repo.AddParameter("@IDROL", rol.OID);
                repo.ExecuteNonQuery();
                repo.Commit();

                foreach (Modulo modulo in rol.Modulos)
                {
                    repo = RepositoryFactory.CreateTransactional(Config.RepositoryName);
                    repo.Nombre = "ROLES_MODULOS_PROC";
                    repo.AddParameter("@ACCION", "ALTA");
                    repo.AddParameter("@IDROL", rol.OID);
                    repo.AddParameter("@IDMODULO", modulo.OID);
                    repo.ExecuteNonQuery();
                    repo.Commit();
                }
        }
        public static void Eliminar(Rol rol)
        {
            rol.Persistencia = EstadoPersistencia.DELETE;
            Guardar(rol);
            rol.Persistencia = EstadoPersistencia.UPDATE;
            rol.Activo = false;
        }
        public static void ReActivar(Rol rol)
        {
            rol.Persistencia = EstadoPersistencia.UNDELETE;
            Guardar(rol);
            rol.Persistencia = EstadoPersistencia.UPDATE;
            rol.Activo = true;
        }

        /// <summary>
        /// Permite consultar los roles
        /// </summary>
        /// <param name="codigo">Codigo, o parte de el, del Rol a consultar</param>
        /// <param name="nombre">Nombre, o parte de el, del Rol a consultar</param>
        /// <param name="activo">El estado de los Roles a consultar</param>
        /// <returns>Todos los Roles que coincidan con los filtros</returns>
        public static List<Rol> Consultar(string codigo, string nombre, bool? activo)
        {
            try
            {
                IRepository repo = RepositoryFactory.Create(Config.RepositoryName);
                repo.Nombre = "ROLES_SP";
                repo.AddParameter("@ACCION", "CONSULTA");
                repo.AddParameter("@ID", null);
                repo.AddParameter("@CODIGO", codigo);
                repo.AddParameter("@NOMBRE", nombre);
                repo.AddParameter("@ACTIVO", activo);
                DataTable dt = repo.ExecuteDataTable();
                List<Rol> result = dt.ToGenericList<Rol>(RolConverter);
                return result;
            }
            catch (Exception ex)
            {
                throw new RolGetException(ex);
            }
        }

        /// <summary>
        /// Permite consultar los roles
        /// </summary>
        /// <returns>Todos los roles</returns>
        public static List<Rol> Consultar()
        {
            return Consultar(null, null, null);
        }

        /// <summary>
        /// Permite consultar los roles activos
        /// </summary>
        /// <param name="codigo">Codigo, o parte de el, del rol a consultar</param>
        /// <param name="nombre">Nombre, o parte de el, del rol a consultar</param>
        /// <returns>Todos los roles que coincidan con los filtros</returns>
        public static List<Rol> Consultar(string codigo, string nombre)
        {
            return Consultar(codigo, nombre, true);
        }

        /// <summary>
        /// Permite consultar los roles segun su estado
        /// </summary>
        /// <param name="activo">El estado de los roles a consultar</param>
        /// <returns>Todos los roles segun el estado seleccionado</returns>
        public static List<Rol> Consultar(bool activo)
        {
            return Consultar(null, null, activo);
        }

        #region Converter
        public static Rol RolConverter(DataRow row)
        {
            return new Rol
            {
                OID = row["rolID"].ToInteger(),
                Persistencia = EstadoPersistencia.UPDATE,
                Codigo = row["rolCODIGO"].ToString(),
                Nombre = row["rolNOMBRE"].ToString(),
                Modulos = ObtenerModulos(row["rolID"].ToInteger())
            };
        }

        #endregion
    }
}
